package rabbitmq

import (
	"context"
	amqp "github.com/rabbitmq/amqp091-go"
	"io"
)

var _ io.WriteCloser = new(Publisher)

// Publisher 发布
type Publisher Entity

func (this *Publisher) Write(p []byte) (int, error) {
	if this.cfg.Debug {
		Log.Writef("[发布] %s", string(p))
	}
	/*
	   exchange：要发送到的交换机名称，对应图中exchangeName。
	   key：路由键，对应图中RoutingKey。
	   mandatory：直接false，不建议使用，后面有专门章节讲解。
	   immediate ：直接false，不建议使用，后面有专门章节讲解。
	   msg：要发送的消息，msg对应一个Publishing结构，Publishing结构里面有很多参数，这里只强调几个参数，其他参数暂时列出，但不解释。
	*/
	err := this.channel.PublishWithContext(this.ctx, "", this.queue.Name, false, false, amqp.Publishing{
		ContentType:     "text/plain", //消息的类型，通常为“text/plain”
		ContentEncoding: "",           //消息的编码，一般默认不用写
		DeliveryMode:    0,            //消息是否持久化，2表示持久化，0或1表示非持久化。
		Priority:        0,            //消息的优先级 0 to 9
		Body:            p,
	})
	return len(p), err
}

func (this *Publisher) Close() error {
	this.conn.Close()
	this.channel.Close()
	return nil
}

func NewPublisher(cfg *Config) (*Publisher, error) {
	return NewPublisherWithContext(context.Background(), cfg)
}

func NewPublisherWithContext(ctx context.Context, cfg *Config) (*Publisher, error) {
	conn, err := amqp.Dial(cfg.Address)
	if err != nil {
		return nil, err
	}
	ch, err := conn.Channel()
	if err != nil {
		return nil, err
	}
	//声明队列
	queue, err := ch.QueueDeclare(cfg.Name, cfg.Durable, cfg.AutoDelete, cfg.Exclusive, cfg.Nowait, nil)
	if err != nil {
		return nil, err
	}
	return &Publisher{
		cfg:     cfg,
		conn:    conn,
		queue:   queue,
		channel: ch,
		ctx:     ctx,
	}, nil
}
